package com.smartstate.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.smartstate.gateway.common.StringUtils;
import com.smartstate.gateway.config.properties.IgnoreWhiteProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.*;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class MyAuthFilter implements GlobalFilter, Ordered {
    @Resource
    private IgnoreWhiteProperties ignoreWhite;
    @Resource
    private DiscoveryClient discoveryClient;
    @Resource
    private RestTemplate restTemplate = new RestTemplate();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String api = exchange.getRequest().getURI().getPath();
        if (StringUtils.matches(api, ignoreWhite.getWhites())) {
            return chain.filter(exchange);
        }
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        String referer = exchange.getRequest().getHeaders().getFirst("referer");
        String methodValue = exchange.getRequest().getMethodValue();
        ServiceInstance instance = discoveryClient.getInstances("sh-data").get(0);
        String sssAdmin = "http://" + instance.getHost() + ":" + instance.getPort();
        sssAdmin+="/home/authentication?api="+api+"&referer="+referer+"&method="+methodValue;
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        headers.add("Authorization",token);
        headers.add("referer",referer);
        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
        ResponseEntity<String> result=null;
        try{
            result = restTemplate.exchange(sssAdmin, HttpMethod.GET, entity, String.class);
        }catch (Exception e){
            //TODO 暂时返回令牌失效
            Map map = new HashMap<>();
            map.put("code",401);
            map.put("message","登陆信息过期，请重新登陆");
            return setUnauthorizedResponse(exchange, map, HttpStatus.UNAUTHORIZED);
        }
        JSONObject jsonObject =JSONObject.parseObject(result.getBody());
        //Map map = JSONObject.parseObject(result.getBody(), Map.class);
        log.info("URL:" + api + ";token:" + token);
        ServerHttpRequest mutableReq = exchange.getRequest().mutate()
                .header("userId", jsonObject.getJSONObject("data").getJSONObject("data").get("id").toString())
                .header("enterpriseId", jsonObject.getJSONObject("data").getJSONObject("data").get("enterpriseId").toString())
                .build();
        ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
        return chain.filter(mutableExchange);
    }

    private Mono<Void> setUnauthorizedResponse(ServerWebExchange exchange, Map map, HttpStatus httpStatus) {
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        response.setStatusCode(httpStatus);
        log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
        return response.writeWith(Mono.fromSupplier(() -> {
            DataBufferFactory bufferFactory = response.bufferFactory();
            return bufferFactory.wrap(JSON.toJSONBytes(map));
        }));
    }

    private String getToken(ServerHttpRequest request) {
        String token = request.getHeaders().getFirst("Authorization");
        if (StringUtils.isNotEmpty(token) && token.startsWith("Bearer ")) {
            token = token.replace("Bearer ", "");
        }
        return token;
    }

    @Override
    public int getOrder() {
        return -200;
    }
}